<?php
class BidDao{
	const  ACTION_COST='COST';
	const  ACTION_EARN='EARN';
	const  LOOP_INTERVAL=100000;
	const  LOOP_MAX_TIMES=10;
	const  LOOP_MAX_TIME=10;
	public $customerId;
	public $bidList=array();
	public $bidclass=array();
	public $retryfile;
	public $begintime;
	public $retry=false;
	public $log;
	public $redis;
	
	public function __construct(){
		$this->init();
	}
	
	public function init(){
		$this->bidclass=array('CASH'=>'CashBidModel','PROMO_BID'=>'PromoBidModel');
		$this->log=new BidLog();
		$this->log->addDir('lock')->logFile('lock');
		$this->redis=new Redis();
		$this->redis->connect('127.0.0.1',6379);
	}
	
	public function addErrorlog(){
		
	}
	
	public function addRetrylist(){
		file_put_contents(Yii::app()->basePath.'/components/bid/log/retry.log', getmypid()."\n",FILE_APPEND);
	} 
	
	public function getmictime(){
		$time=explode(' ', microtime());
		return $time[1]+$time[0];
	}
	
	public function run(){
		$begintime=time();
		$times=0;
		$timeOut = time() + 10;
		do{
			$this->retry = time() < $timeOut;
			$this->log->addLog('CONFLICT', 'times is'.$times.' pid is '.getmypid());
			if ($this->lock()) {
				$this->log->addLog('CONFLICT', 'times is'.$times.' pid is '.getmypid());
				usleep(self::LOOP_INTERVAL);
				continue;
			}
			
			$starttime=$this->getmictime();
			$this->retry=false;
			foreach ($this->bidList as $bid){
				$transaction=Yii::app()->db->getCurrentTransaction();
				$transaction=($transaction)?$transaction:Yii::app()->db->beginTransaction();
				try {
					if ($bid->validate()) {
						$bid->created=time();
						$bid->save();
					}else{
						$this->addErrorlog();
						continue;
					}
					$transaction->commit();
				}catch (Exception $e){
					$transaction->rollback();
				}
			}
			$this->unlock();
			return true;			
		
		
		}while ($this->retry);
		$this->addRetrylist();
	}
	
	public function pushBidList($bidmodel){
		$this->bidList[]=$bidmodel;
		return $this;
	}
	
	
	public function setList($list){
		$this->bidList=$list;
		return $this;
	}
	
	public function getList(){
		return $this->bidList;
	}
	
	public function setCustomerId($id){
		$this->customerId=$id;
		return $this;
	}
	
	public function cost($amount,$bidType,$sourceType,$note=null){
		$bidmodel=new $this->bidclass[$bidType]();
		$bidmodel->attributes=array(
				'bid_type'			=>$bidType,
				'bid_source_type'	=>$sourceType,
				'customerId'		=>$this->customerId,
				'note'				=>$note,
				'amount'			=>-$amount,
				'action'			=>self::ACTION_COST,
		);
		$this->pushBidList($bidmodel);
		return $this;
	}
	
	public function earn($amount,$bidType,$sourceType,$note=null){
		$bidmodel=new $this->bidclass[$bidType]();
		$bidmodel->attributes=array(
			'bid_type'			=>$bidType,
			'bid_source_type'	=>$sourceType,
			'customerId'		=>$this->customerId,
			'note'				=>$note,
			'amount'			=>$amount,
			'action'			=>self::ACTION_EARN,
		);
		$this->pushBidList($bidmodel);
		return $this;	
	}
	
	public function lock(){
		return !$this->redis->setnx('lock','lkjfel');
	}
	
	public function unlock(){
		return $this->redis->delete('lock');
	}
}